% modules.tex
% This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 New Zealand License.
% To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/nz
% or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.


\chapter{Quelques modules de Python}\label{app:modules}\index{modules}

Python a un grand nombre de modules disponibles pour faire toutes sortes de choses. Vous pouvez vous renseigner sur ces derniers en lisant la documentation de Python à l'adresse suivante \url{http://docs.python.org/modindex.html}. Quelqu'un des modules les plus utiles sont décrits ici. Un avertissement si vous décidez de regarder la documentation de Python: la liste des modules est vraiment longue et certains de ces modules sont très compliqués.

\section{Le module « \texttt{random} »}\index{modules!random}
\subsection{Introduction à random}
Si vous avez déjà joué à faire deviner un chiffre entre un et cent ou si vous avez déjà lancé un dé, vous savez déjà ce que fait le module « \texttt{random} ». Le module « \texttt{random} » contient un certain nombre de fonctions qui sont utiles pour générer des données aléatoires, c'est à dire tirées au hasard.

De toutes les fonctions de « \texttt{random} », les plus utiles sont sans contestation possible les fonctions \verb+randint+\index{modules!random!randint}, \verb+choice+ et \verb+shuffle+. 

\subsection{randint}
La première fonction, \verb+randint+, prend un nombre entier au hasard entre le premier argument et le deuxième argument, par exemple entre un et six ou un et cent. Par exemple:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import random
>>> print(random.randint(1, 6))
5
>>> print(random.randint(1, 100))
861
>>> print(random.randint(1000, 5000))
3795
\end{Verbatim}

Nous pouvons utiliser cette fonction pour créer un jeu de devinette, simple (et ennuyant) en utilisant une boucle tant que:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
import random
import sys
nombre = random.randint(1, 100)
print('''Le but est de deviner un nombre 1 and 100.
Vous pouvez quitter à tout moment avec "q" puis entrée.''')
while True:
    print('Proposez un nombre 1 and 100 :')
    prop = sys.stdin.readline()
    if prop=="q" :
        print('Vous avez perdu.')
        break
    i = int(prop)
    if i == nombre:
        print('Vous avez deviné juste!')
        break
    elif i < nombre:
        print('Essayez plus haut.')
    elif i > nombre:
        print('Essayer plus bas.')
\end{Verbatim}

\subsection{choice}

Utilisez « \verb+choice+\index{modules!random!choice} »,  si vous avez une liste et que vous voulez tirer un élément au hasard. Par exemple:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import random
>>> liste1 = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' ]
>>> print(random.choice(liste1))
c
>>> liste2 = [ 'glace', 'pancakes', 'pavlova' ]
>>> print(random.choice(liste2))
pancakes
\end{Verbatim}

Et finalement, utilisez « \verb+shuffle+\index{modules!shuffle} » si vous voulez mélanger aléatoirement une liste (comme pour mélanger des cartes):

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import random
>>> liste1 = [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' ]
>>> liste2 = [ 'glace', 'pancakes', 'pavlova' ]
>>> random.shuffle(liste1)
>>> print(liste1)
['h', 'e', 'a', 'b', 'c', 'g', 'f', 'd']
>>> random.shuffle(liste2)
>>> print(list2)
>>> ['pancakes', 'glace', 'pavlova']
\end{Verbatim}

\section{Le module « \texttt{sys} »}\index{modules!sys}
\subsection{Introduction à sys}

Le module « \verb+sys+ » contient des fonctions « système » utiles. Le terme système est juste un mot étrange pour désigner tout ce qui fait la liaison entre le matériel (l'ordinateur que l'on peut toucher) et les logiciels (dont le votre en particulier). Certaines des fonctions les plus utiles en Python sont contenues dans le module « \texttt{sys} ». Entre autres les foncions \verb+exit+, \verb+stdin+, \verb+stdout+ et \verb+version+.
\subsection{exit}

La fonction \verb+exit+\index{modules!sys!exit} est une manière d'arrêter Python ainsi que la console le cas échéant. Par exemple si vous tapez:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import sys
>>> sys.exit()
\end{Verbatim}

La console Python va s'arrêter. Selon que vous utilisez Windows, Mac ou Linux, un certain nombre de choses peuvent arriver --- mais, à la fin, le résultat sera le même: La console Python s'arrêtera.
\subsection{stdin}

La fonction « \verb+stdin+\index{modules!sys!stdin} » a été utilisée ailleurs dans ce livre (voir \autoref{chap:recyclage}) pour demander à quelqu'un utilisant un programme d'entrée des informations. Par exemple:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import sys
>>> mavaleur = sys.stdin.readline()
Ceci est ma valeur.
>>> print(mavaleur)
Ceci est ma valeur.
\end{Verbatim}
\subsection{stdout}

La fonction « \verb+stdout+\index{modules!sys!stdout} » est l'opposé de « \texttt{stdin} » --- elle est utilisée pour écrire des messages. D'une certaine manière elle ressemble à « \texttt{print} » mais elle fonctionne plus comme « \texttt{file} ». Quelques fois il est plus pratique d'utiliser « \texttt{stdout} » plutôt que « \texttt{print} ».

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import sys
>>> l = sys.stdout.write('Ceci est un test.')
Ceci est un test.>>>
\end{Verbatim}

Remarquez-vous ou l'invite « \texttt{>>>} » réapparait? Ce n'est pas une erreur, elle réapparait à la fin du message. C'est parce que, contrairement à « \texttt{print} », « \texttt{stdout.write} » ne rajoute pas automatiquement un retour à la ligne. Pour faire la même chose avec « \texttt{write} »  nous pouvons faire comme cela:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import sys
>>> l = sys.stdout.write('Ceci est un test.\n')
Ceci est un test.
>>>
\end{Verbatim}
ou encore: 
\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import sys
>>> l = sys.stdout.write('''Ceci est un test.
''')
Ceci est un test.
>>>
\end{Verbatim}

La fonction « \texttt{stdout.write} » retourne le nombre de caractères écrits ---essayez de faire « \texttt{print(l)} » ou « \verb+print(sys.stdout.write('Ceci est un test.\n'))+ », pour voir le résultat.

Le « \texttt{{\textbackslash}n} » est le caractère \emph{d'échappement}\index{caractère d'échappement} pour une nouvelle ligne, c'est à dire ce que vous avez quand vous appuyez sur la touche entrée. Un caractère d'échappement est une suite de quelques caractères que l'on utilise dans les chaîne quand on ne peut pas taper directement de caractère\footnote{L'usage des triples apostrophes en Python réduit notablement l'usage des caractères d'échappement par rapport à d'autres langages.}. Par exemple si vous voulez créer une chaîne avec un saut de ligne au milieu, sans utiliser de triple apostrophe, vous aurez une erreur:
\begin{Verbatim}[frame=single,rulecolor=\color{red},label=ne fonctionne pas]
>>> s = 'test test 
  File "<stdin>", line 1
    s = 'test test 
                  ^
SyntaxError: EOL while scanning single-quoted string
\end{Verbatim}

À la place vous pouvez utiliser le caractère d'échappement de du retour à la ligne:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> s = 'test test\ntest'
\end{Verbatim}

Pour finir avec « \texttt{sys} », l'attribut « \verb+version+\index{modules!sys!version} » est utilisée pour afficher la version de Python que vous utilisez:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import sys
>>> print(sys.version)
3.0.1+ (r301:69556, Apr 15 2009, 15:59:22) 
[GCC 4.3.3]
\end{Verbatim}

\section{Le module « \texttt{locale} »}\index{modules!locale}
Le module « \texttt{locale} » est utilisé pour « localiser », c'est à dire rendre utilisable localement par un utilisateur, des fonctions de Python.

Il est généralement utilisé sous la forme:
\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import locale
>>> locale.setlocale(locale.LC_ALL,'')
\end{Verbatim}

Cet appel permet à Python d'utiliser la langue locale du système. Il est à noter que toutes les langues du monde ne sont pas prévues et qu'il peut être nécessaire de réaliser des traductions.

\section{Le module « \texttt{time} »}\index{modules!time}
\subsection{Non je ne radote pas: time.time }

Le module « \texttt{time} » contient des fonctions pour gérer le temps et afficher des résultats compréhensibles par l'utilisateur. Le mot « \emph{time} » signifie temps en anglais. Néanmoins, si vous essayer la fonction qui semble la plus simple « \verb+time+)\index{modules!time!time (fonction)} », le résultat pourrait bien être différent de ce que vous imaginiez:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> print(time.time())
1250020582.13
\end{Verbatim}

Le nombre retourné par la fonction « \texttt{time} »  est le nombre de secondes écoulées depuis le 1\up{er} janvier 1970 à 00:00:00 (zéro heure) en temps universel coordonnée (c'est à dire une heure de moins qu'en France métropolitaine en hiver et deux heures en été). Vous pouvez penser que cela n'est pas très utile, néanmoins cela l'est, des fois. Par exemple, si vous créez un programme et que vous voulez savoir à quelle vitesse s'exécute-t'il, vous pouvez enregistrer l'heure au début puis faire la différence avec l'heure à la fin pour connaitre le temps passé.

Par exemple, combien cela prendra-t'il de temps pour afficher tous les nombre de 1 à 100 000?  Nous pouvons facilement créer une fonction pour les afficher:
\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> def compter(max):
...     for x in range(1, max+1):
...         print(x)
\end{Verbatim}

Puis, nous pouvons appeler la fonction:
\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> compter(100000)
\end{Verbatim}

Mais si nous voulons savoir combien de temps cela prend, nous pouvons modifier la fonction et utiliser le module  « \texttt{time} »:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> def compter(max):
...     t1 = time.time()
...     for x in range(0, max):
...         print(x)
...     t2 = time.time()
...     print("Compter jusqu'à %s a pris  %s secondes" % (max,t2-t1))
\end{Verbatim}

Si nous utilisons à nouveau notre fonction, nous avons alors:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> compter(100000)
1
2
3
.
.
.
99997
99998
99999
100000
Compter jusqu'à 100000 a pris  18.7396810055 secondes
\end{Verbatim}

Comment cela fonctionne-t'il? La première fois, nous appelons la fonction « \texttt{time} », puis nous assignons le résultat à la variable « \texttt{t1} ». Nous créons alors un itérateur pour afficher tous les nombres voulus. Puis nous appelons à nouveau la fonction « \texttt{time} » et nous mettons le résultat dans la variable « \texttt{t2} ». Comme le parcours de la boucle a pris du temps la valeur de « \texttt{t2} » est plus grande (plus tard) que « \texttt{t1} », le nombre de seconde depuis  le 1\up{er} janvier 1970 a augmenté). Donc si nous soustrayons « \texttt{t1} » à « \texttt{t2} » nous avons le nombre de secondes qu'il a fallut pour afficher les nombres.

D'autres fonctions sont disponibles dans le module « \texttt{time} » dont: \verb+asctime+, \verb+ctime+, \verb+localtime+, \verb+sleep+, \verb+strftime+ et \verb+strptime+.

\subsection{asctime}


La fonction « \verb+asctime+\index{modules!time!asctimes} » prend une date sous la forme d'un n-uplet (rappelez-vous un n-uplet est une liste de valeurs qui ne peut pas être changé et la convertit en une forme lisible (pour les anglophones). Vous pouvez aussi l'appeler sans argument, elle affichera alors la date et l'heure actuelle:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> print(time.asctime())
Sun May 27 20:11:12 2007
\end{Verbatim}

Pour l'appeler avec un argument nous devons d'abord créer un n-uplet avec les valeurs correctes associées à une date (c'est à dire qui correspondent à quelque chose). Commençons par assigner un n-uplet à la variable « \texttt{t} »:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> t = (2007, 5, 27, 10, 30, 48, 6, 0, 0)
\end{Verbatim}

Les valeurs dans le n-uplet sont dans l'ordre: l'année, le mois, le jour, les heures, les minutes, les secondes, le jour (0 pour lundi, 1 pour mardi et ainsi de suite jusqu'à 6 pour dimanche), le jour de l'année (obligatoire mais non traité par « \texttt{asctime} ») et enfin l'existence d'un éventuel changement d'heure pour l'économie d'énergie (1 si économie d'énergie, 0 sinon).

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> t = (2007, 5, 27, 10, 30, 48, 6, 0, 0)
>>> print(time.asctime(t))
Sun May 27 10:30:48 2007
\end{Verbatim}

Mais faites attention à mettre des valeurs valides dans le n-uplet. Vous pouvez obtenir un résultat qui n'est pas possible si vous rentrez n'importe quoi:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> t = (2007, 5, 27, 10, 30, 48, 0, 0, 0)
>>> print(time.asctime(t))
Mon May 27 10:30:48 2007
\end{Verbatim}

Ici, nous avons fixé la valeur du jour de la semaine à zéro (pour lundi, \emph{monday}) alors que le 27 mai 2007 était un dimanche (6).

\subsection{ctime}

La fonction « \texttt{ctime} »\index{modules!time!ctime} est utilisée pour convertir un nombre de secondes en un texte lisible.  Par exemple nous pouvons l'utiliser avec la fonction « \texttt{time} » vue au début de cette section.

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> t = time.time()
>>> print(t)
1180264952.57
>>> print(time.ctime(t))
Sun May 27 23:22:32 2007
\end{Verbatim}


\subsection{localtime}

La fonction « \texttt{localtime} »\index{modules!time!localtime} retourne la date et l'heure actuelles comme un n-uplet dont la séquence est la même que celle que nous venons d'utiliser. 

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> print(time.localtime())
(2007, 5, 27, 23, 25, 47, 6, 147, 0)
\end{Verbatim}


Nous pouvons aussi fournir cette valeur à « \texttt{asctime} »:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> t = time.localtime()
>>> print(time.asctime(t))
Sun May 27 23:27:22 2007
\end{Verbatim}

\subsection{sleep}

La fonction « \texttt{sleep} »\index{modules!time!sleep} est vraiment utilise quand vous devez retarder un programme pour un certain temps. Le mot \emph{sleep} signifie dormir en anglais. Par exemple, si vous voulez afficher un nombre chaque seconde la boucle suivante ne sera pas adaptée:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> for x in range(61):
...     print(x)
...
1
2
3
4
\end{Verbatim}

Elle imprimera immédiatement tous les nombre de un à soixante. Néanmoins si vous dites à Python de dormir entre chaque affichage, vous aurez un résultat beaucoup plus proche de ce que vous voulez:

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> for x in range(61):
...     print(x)
...     time.sleep(1)
...
\end{Verbatim}
Il y aura ainsi entre chaque affichage un délais. Pour être exact le temps d'affichage est non nul donc l'affichage des soixante nombres prendra dans ce cas un peu plus d'une minute (soixante temps d'affichage plus soixante secondes d'attente). Idéalement il faudrait donc ajouter un peu moins qu'une seconde à chaque pas, néanmoins l'auto-adaptation de ce délais sort du cadre de ce livre.

Dire à l'ordinateur de dormir peut ne pas sembler utile alors quand fait c'est souvent important. Pensez à votre réveil, quand vous appuyez sur le bouton, il arrête de bipper pour quelques minutes (au moins jusqu'à ce que quelqu'un vous appelle pour le petit déjeuner). La fonction « \texttt{sleep} » pourrait être utilisée dans ce genre de situation.

\subsection{strftime}

La fonction « \texttt{strftime} »\index{modules!time!strftime} est utilisée pour réaliser l'affichage de la date et de l'heure à votre convenance. Attention au « \texttt{f} » de « \texttt{strftime} », il existe une autre fonction « \texttt{strptime} » avec un « \texttt{p} » qui converti une chaîne en n-uplet.
Commençons d'abord par examiner « \texttt{strftime} ».
Juste avant nous avons vu comment changer un n-uplet en chaîne en utilisant « \texttt{asctime} ».

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> t = (2007, 5, 27, 10, 30, 48, 6, 0, 0)
>>> print(time.asctime(t))
Sun May 27 10:30:48 2007
>>> t=time.localtime()
>>> print(time.asctime(t))
Thu Aug 13 08:56:15 2009
\end{Verbatim}



La fonction « \texttt{localtime} » fournit un n-uplet déjà renseigné avec toutes des informations correspondant à l'heure locale (non universelle, qui est affichée sur votre ordinateur) à l'instant où la commande est lancée si aucun argument n'est donné. La commande « \texttt{localtime} » peut aussi prendre en argument un nombre de secondes depuis le premier janvier 1970.   

Cela fonctionne bien pour les anglophones, mais si vous n'aimez pas la manière dont la chaîne est présenté --- comment faire si vous voulez afficher la date et pas l'heure, si vous voulez avoir un résultat en français plutôt qu'en anglais?

\begin{Verbatim}[frame=single,rulecolor=\color{gray},label=code]
import time,locale

t=time.localtime()
print(time.strftime('%d %b %Y', t))

locale.setlocale(locale.LC_ALL,'')
print(time.strftime('%d %b %Y', t))
\end{Verbatim}


\begin{Verbatim}[frame=single,rulecolor=\color{gray},label=résultat]
13 Aug 2009
13 août 2009
\end{Verbatim}

Comme vous pouvez voir « \texttt{strftime} » prend deux arguments: le premier est le format souhaité de la date (décrivant comment la date ou l'heure vont être affichés) et le second est un n-uplet qui contient une date. Ici nous avons généré le n-uplet avec la commande « \texttt{localtime} ». Le format « \texttt{\%d \%b \%Y} » est une autre manière de dire: affiche le jour, le mois puis l'année. Remarquez que l'utilisation de « \texttt{setlocale} » permet d'afficher ce résultat dans la langue choisi par l'utilisateur pour son système d'exploitation.

Nous pouvons aussi afficher le mois comme un nombre:
\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> print(time.strftime('%d/%m/%Y', t))
13/08/2009
\end{Verbatim}

Ce format est une manière de dire: affiche le jour, puis une barre oblique, puis le mois sous la forme d'un nombre, puis une barre oblique et finalement l'année.
Il y a différentes possibilités que vous pouvez utiliser pour formater la date\index{date/time formats}:

\begin{center}
\begin{tabular}{|l|p{12cm}|}
\hline
\%a & le nom raccourci du jour de la semaine (lun., mar., mer., jeu., ven., sam. ou dim.) \\
\hline
\%A & le nom jour de la semaine  \\
\hline
\%b & le nom raccourci du mois \\
\hline
\%B & le nom du mois \\
\hline
\%c & la date et l'heure complète dans un format similaire à « \texttt{asctime} » mais dans la langue locale\\
\hline
\%d & le numéro du jour dans le mois\\
\hline
\%H & le nombre d'heures sur une base de vingt quatre heures (14 pour deux heures de l'après -midi) \\
\hline
\%I & le nombre d'heures sur une base de douze heures (2 pour quatorze heures)\\
\hline
\%j & le numéro du jour dans l'année\\
\hline
\%m & le numéro du mois \\
\hline
\%M & le nombre de minutes \\
\hline
\%p & non disponible en français, en anglais le matin sous la forme AM ou l'après-midi sous la forme PM \\
\hline
\%S & le nombre de secondes\\
\hline
\%U & le numéro de la semaine dans l'année \\
\hline
\%w & le numéro du jour dans la semaine (dimanche vaut 0, lundi 1...) \\
\hline
\%x & la date sous une forme numérique simple: jour/mois/année (03/25/07) si la langue est européenne  \\
\hline
\%X & l'heure sous une forme numérique simple: heure:minutes:secondes (10:30:53) \\
\hline
\%y & l'année sur deux chiffres (09 pour 2009) \\
\hline
\%Y & l'année sur quatre chiffres (2009) \\
\hline
\end{tabular}
\end{center}
\subsection{strptime}

La fonction « \texttt{strptime} »\index{modules!time!strptime} est presque l'inverse de la fonction « \texttt{strftime} » --- elle prend une chaîne comme argument et la convertie en un n-uplet qui contient la date et l'heure. Elle prend comme format une chaîne sous la même forme (\%d, \%H...):


\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time,locale
>>> locale.setlocale(locale.LC_ALL,'')
>>> t = time.strptime('13 août 2009', '%d %b %Y')
>>> print(t)
time.struct_time(tm_year=2009, tm_mon=8, tm_mday=13, tm_hour=0, 
tm_min=0, tm_sec=0, tm_wday=3, tm_yday=225, tm_isdst=-1)
\end{Verbatim}

Si la date avait été sous la forme jour/mois/année (par exemple 01/02/2007), nous pourrions utiliser « \texttt{t = time.strptime('01/02/2007', '\%d/\%m/\%Y')} » ou encore « \texttt{t = time.strptime('01/02/2007', '\%x')} ».


Nous pouvons combiner « \texttt{strptime} » et « \texttt{strftime} » pour convertir une chaîne d'un format vers un autre.

\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> import time
>>> def convert_date(datestring, format1, format2):
...     t = time.strptime(datestring, format1)
...     return time.strftime(format2, t)
...
\end{Verbatim}

Nous pouvons utiliser cette fonction en passant une date sous la forme d'une chaîne, le format de cette dernière et le format souhaité.


\begin{Verbatim}[frame=single,rulecolor=\color{gray}]
>>> print(convert_date('03/05/2007', '%m/%d/%Y', '%d %B %Y'))
05 mars 2007
\end{Verbatim}
